package com.xbongbong.pro.statistic.service.result;

import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.JsonHelperUtil;
import com.xbongbong.paas.toolbox.util.PageHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.enums.global.ChartCategoryEnum;
import com.xbongbong.pro.service.toolbox.statistic.util.ChartResultUtil;
import com.xbongbong.pro.statistic.constant.ChartI18Constant;
import com.xbongbong.pro.statistic.enums.SystemCodeEnum;
import com.xbongbong.pro.statistic.enums.ValueTypeEnum;
import com.xbongbong.pro.statistic.pojo.StockInfoPojo;
import com.xbongbong.pro.statistic.pojo.vo.StockInfoVO;
import com.xbongbong.pro.statistic.result.pojo.ChartResultPojo;
import com.xbongbong.pro.statistic.result.pojo.vo.ChartResultDetailVO;
import com.xbongbong.pro.statistic.result.pojo.vo.ResultDataTableVO;
import com.xbongbong.pro.statistic.result.pojo.vo.ResultTableVO;
import com.xbongbong.saas.constant.PageConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.InstockProductEntity;
import com.xbongbong.saas.domain.entity.OutstockProductEntity;
import com.xbongbong.saas.enums.InstockTypeEnum;
import com.xbongbong.saas.enums.OutstockTypeEnum;
import com.xbongbong.saas.enums.business.InstockEnum;
import com.xbongbong.saas.enums.business.OutstockEnum;
import com.xbongbong.saas.service.toolbox.help.ProductHelp;
import com.xbongbong.saas.toolbox.help.SortHelp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 *
 * @author zcp
 * @version v1.0
 * @date 2019/4/8 11:19
 * @since v1.0
 */
@Service
public class JxcStockResult extends ChartResultParentService implements ChartResultSystem {
    private static final Logger LOG = LoggerFactory.getLogger(JxcStockResult.class);
    @Resource
    private ProductHelp productHelp;

    @Override
    public Object getTarget(ChartResultPojo chartResultPojo, ChartResultDetailVO chartResultDetailVO) throws XbbException {
        SystemCodeEnum systemCodeEnum = chartResultPojo.getSystemCodeEnum();
        switch (systemCodeEnum) {
            case STOCK_TABLE_CHART:
                return stockTableChart(chartResultPojo, chartResultDetailVO);
            case STOCK_PRODUCT_WORK_ORDER_TOP:
                return stockProductWorkOrderTop(chartResultPojo, chartResultDetailVO);
            default:
                break;
        }
        return null;
    }

    @Override
    public Object getValueTarget(ChartResultPojo chartResultPojo) throws XbbException {
        SystemCodeEnum systemCodeEnum = chartResultPojo.getSystemCodeEnum();
        switch (systemCodeEnum) {
            case IN_STOCK_PRODUCT_BOARD:
                return instockProductBoard(chartResultPojo);
            case OUT_STOCK_PRODUCT_BOARD:
                return outstockProductBoard(chartResultPojo);
            default:
                break;
        }
        return null;
    }

    /**
     * 库存流水汇总表
     * @param chartResultPojo
     * @param chartResultDetailVO
     * @return com.xbongbong.pro.statistic.result.pojo.vo.ChartResultDetailVO
     * @throws XbbException
     * @author zcp
     * @date 2019/4/9 14:57
     * @since v1.0
     * @version v1.0
     */
    public ChartResultDetailVO stockTableChart(ChartResultPojo chartResultPojo, ChartResultDetailVO chartResultDetailVO) throws XbbException {
        ChartResultUtil.formatPage(chartResultPojo, PageConstant.DEFAULT_PAGE_SIZE_SMALL);
        Integer page = chartResultPojo.getPage();
        Integer pageSize = chartResultPojo.getPageSize();
        String corpid = chartResultPojo.getCorpid();
        //存放出入库所有负责人ids
        Set<String> managerIdIn = new HashSet<>();
        StockInfoPojo stockInfoPojo = new StockInfoPojo();
        //----------------------处理入库----------------------
        stockInfoPojo = getInStockInfoPojo(chartResultPojo, managerIdIn, stockInfoPojo);
        //----------------------处理出库----------------------
        stockInfoPojo = getOutStockInfoPojo(chartResultPojo, managerIdIn, stockInfoPojo);
        //----------------------处理出入库的信息、分页等----------------------
        List<List<ResultDataTableVO>> tableData = new ArrayList<>();
        //员工id--员工名称
        Map<String, String> userNameMap = commonHelp.getUserNameMapByIds(corpid, managerIdIn);
        //入库id--出入库信息
        Map<Long, StockInfoVO> instockMap = stockInfoPojo.getInstockMap();
        List<InstockProductEntity> instockProductList = stockInfoPojo.getInstockProductList();
        for (InstockProductEntity entity : instockProductList) {
            //对应出入库单，不会为空（因为出入库产品就是基于出入库id查出的）
            StockInfoVO stockInfoVO = instockMap.get(entity.getIntoWarehouseId());
            List<ResultDataTableVO> voList = new ArrayList<>();
            String warehouseName = StringUtil.isEmpty(entity.getWarehouseName()) ? "" : entity.getWarehouseName();
            String managerName = userNameMap.getOrDefault(stockInfoVO.getManagerId(), "");
            voList.add(new ResultDataTableVO(managerName, null));
            voList.add(new ResultDataTableVO(stockInfoVO.getSerialNo(), null));
            voList.add(new ResultDataTableVO(stockInfoVO.getRefName(), null));
            ResultDataTableVO productNoVo = new ResultDataTableVO(entity.getProductNo(), null);
            //把主键id置入，方便检查数据
            productNoVo.setDataId(entity.getProductId());
            voList.add(productNoVo);
            voList.add(new ResultDataTableVO(entity.getProductName(), null));
            voList.add(new ResultDataTableVO(entity.getProductSpecification(), null));
            voList.add(new ResultDataTableVO(entity.getCategoryName(), null));
            voList.add(new ResultDataTableVO(entity.getProductUnit(), null));
            voList.add(new ResultDataTableVO(StringUtil.formatDouble(entity.getProductNum()), null));
            voList.add(new ResultDataTableVO(warehouseName, null));
            voList.add(new ResultDataTableVO(stockInfoVO.getTypeName(), null));
            voList.add(new ResultDataTableVO(stockInfoVO.getTime(), null));
            tableData.add(voList);
        }
        Map<Long, StockInfoVO> outstockMap = stockInfoPojo.getOutstockMap();
        List<OutstockProductEntity> outstockProductList = stockInfoPojo.getOutstockProductList();
        for (OutstockProductEntity entity : outstockProductList) {
            StockInfoVO stockInfoVO = outstockMap.get(entity.getOutWarehouseId());
            List<ResultDataTableVO> voList = new ArrayList<>();
            String warehouseName = StringUtil.isEmpty(entity.getWarehouseName()) ? "" : entity.getWarehouseName();
            String managerName = userNameMap.getOrDefault(stockInfoVO.getManagerId(), "");
            voList.add(new ResultDataTableVO(managerName, null));
            voList.add(new ResultDataTableVO(stockInfoVO.getSerialNo(), null));
            voList.add(new ResultDataTableVO(stockInfoVO.getRefName(), null));
            ResultDataTableVO productNoVo = new ResultDataTableVO(entity.getProductNo(), null);
            //把主键id置入，方便检查数据
            productNoVo.setDataId(entity.getProductId());
            voList.add(productNoVo);
            voList.add(new ResultDataTableVO(entity.getProductName(), null));
            voList.add(new ResultDataTableVO(entity.getProductSpecification(), null));
            voList.add(new ResultDataTableVO(entity.getCategoryName(), null));
            voList.add(new ResultDataTableVO(entity.getProductUnit(), null));
            voList.add(new ResultDataTableVO(StringUtil.formatDouble(entity.getProductNum()), null));
            voList.add(new ResultDataTableVO(warehouseName, null));
            voList.add(new ResultDataTableVO(stockInfoVO.getTypeName(), null));
            voList.add(new ResultDataTableVO(stockInfoVO.getTime(), null));
            tableData.add(voList);
        }
        //分页
        Integer rowCounts = tableData.size();
        PageHelper pageHelper = PageHelperUtil.initPageHelper(rowCounts, page, pageSize, PageConstant.DEFAULT_PAGE_SIZE_SMALL);
        Integer fromIndex = (page - 1) * pageSize;
        Integer toIndex = fromIndex + pageSize;
        if(toIndex > rowCounts) {
            toIndex = rowCounts;
        }
        List<List<ResultDataTableVO>> subTableData = tableData.subList(fromIndex, toIndex);
        List<String> title = Arrays.asList(I18nMessageUtil.getMessage(ChartI18Constant.STOCK_TABLE_CHART_TITLE).split(","));
        ResultTableVO table = new ResultTableVO();
        table.setTitle(systemChartHelp.titleNumRight(title));
        table.setData(subTableData);
        table.setPageHelper(pageHelper);
        table.setTableName(I18nMessageUtil.getMessage(ChartCategoryEnum.STOCK_TABLE_CHART.getName()));
        chartResultDetailVO.setTable(table);
        return chartResultDetailVO;
    }

    /**
     * 工单出库产品排行
     * @param chartResultPojo
     * @param chartResultDetailVO
     * @return com.xbongbong.pro.statistic.result.pojo.vo.ChartResultDetailVO
     * @throws XbbException
     * @author zcp
     * @date 2019/4/9 16:58
     * @since v1.0
     * @version v1.0
     */
    public ChartResultDetailVO stockProductWorkOrderTop(ChartResultPojo chartResultPojo, ChartResultDetailVO chartResultDetailVO) throws XbbException {
        List<Integer> typeIn = Arrays.asList(OutstockTypeEnum.WORK_ORDER_OUTSTOCK.getCode());
        Set<Long> outstockIdIn = formHelp.getOutstockIdIn4Types(chartResultPojo, typeIn);
        //出库单关联的入库产品--内部处理好产品编号、产品分类、规格等信息
        List<OutstockProductEntity> outstockProductList = productHelp.getOutstockProduct(outstockIdIn, chartResultPojo.getCorpid());
        //产品id--销售产品数量
        Map<Long, Double> numProductMap = new HashMap<>(outstockProductList.size());
        //id-名称map
        Map<Long, String> nameProductMap = new HashMap<>(outstockProductList.size());
        for (OutstockProductEntity entity : outstockProductList) {
            Long productId = entity.getProductId();
            Double num = entity.getProductNum();
            Double count = numProductMap.get(productId);
            if (count == null) {
                count = 0d;
                String productName = entity.getProductName();
                String productSpecification = entity.getProductSpecification();
                productName = productSpecification == null || Objects.equals(productSpecification, "") ? productName : productName  + StringConstant.POINT + entity.getProductSpecification();
                nameProductMap.put(productId, productName);
            }
            count += num;
            numProductMap.put(productId, count);
        }
        //productId--全公司排名值
        Map<Long, Integer> corpRankMapTop10 = SortHelp.sortMapValueDouble4KeyLong(numProductMap, SortHelp.TOP_10);
        String seriesName = "出库产品";
        chartResultPojo.setValueTypeEnum(ValueTypeEnum.VALUE_DOUBLE);
        return systemChartHelp.result4Top(seriesName, corpRankMapTop10, numProductMap, nameProductMap, chartResultPojo, chartResultDetailVO);
    }
    /**
     * 入库产品销量
     * @param chartResultPojo
     * @return java.lang.String 
     * @throws XbbException
     * @author zcp
     * @date 2019/4/16 10:41
     * @since v1.0
     * @version v1.0
     */
    public String instockProductBoard(ChartResultPojo chartResultPojo) throws XbbException {
        List<PaasFormDataEntityExt> stockList = formHelp.getInstockList(chartResultPojo, Collections.singletonList(FieldTypeEnum.DATAID.getAlias()));
        //入库单关联的入库产品
        Set<Long> stockIdIn = new HashSet<>();
        for (PaasFormDataEntityExt entityExt : stockList) {
            stockIdIn.add(entityExt.getDataId());
        }
        Double productNum = formHelp.getInstockProductNumSum(chartResultPojo.getCorpid(), stockIdIn);
        return StringUtil.formatDouble(productNum);
    }
    /**
     * 出库产品销量
     * @param chartResultPojo
     * @return java.lang.String
     * @throws XbbException
     * @author zcp
     * @date 2019/4/16 10:42
     * @since v1.0
     * @version v1.0
     */
    public String outstockProductBoard(ChartResultPojo chartResultPojo) throws XbbException {
        List<PaasFormDataEntityExt> stockList = formHelp.getOutstockList(chartResultPojo, Collections.singletonList(FieldTypeEnum.DATAID.getAlias()));
        //出库单关联的出库产品
        Set<Long> stockIdIn = new HashSet<>();
        for (PaasFormDataEntityExt entityExt : stockList) {
            stockIdIn.add(entityExt.getDataId());
        }
        Double productNum = formHelp.getOutstockProductNumSum(chartResultPojo.getCorpid(), stockIdIn);
        return StringUtil.formatDouble(productNum);
    }

    /**
     * 得到入库产品相关信息pojo
     * @param chartResultPojo 参数pojo
     * @param managerIdIn 负责人userId数组
     * @param stockInfoPojo 出入库存pojo
     * @return java.util.List<com.xbongbong.saas.domain.entity.InstockProductEntity> 
     * @throws XbbException
     * @author zcp
     * @date 2019/4/8 22:41
     * @since v1.0
     * @version v1.0
     */
    private StockInfoPojo getInStockInfoPojo(ChartResultPojo chartResultPojo, Set<String> managerIdIn, StockInfoPojo stockInfoPojo) throws XbbException {
        InstockEnum enumManagerId = InstockEnum.MANAGER_ID;
        InstockEnum enumType = InstockEnum.TYPE;
        InstockEnum enumTime = InstockEnum.TIME;
        InstockEnum enumRefId = InstockEnum.REF_ID_LINKED_TEXT;
        List<String> fieldList = Arrays.asList(FieldTypeEnum.DATAID.getAlias(), FieldTypeEnum.OWNERID.getAlias(), FieldTypeEnum.SERIALNO.getAlias(), InstockEnum.getAttrConnectData(enumManagerId), InstockEnum.getAttrConnectData(enumType), InstockEnum.getAttrConnectData(enumTime), InstockEnum.getAttrConnectData(enumRefId));
        List<PaasFormDataEntityExt> instockList = formHelp.getInstockList(chartResultPojo, fieldList);
        Set<Long> instockIdIn = new HashSet<>();
        Map<Long, StockInfoVO> instockMap = new HashMap<>(instockList.size());
        String managerIdAttr = enumManagerId.getAttr();
        String typeAttr = enumType.getAttr();
        String timeAttr = enumTime.getAttr();
        String refIdAttr = enumRefId.getAttr();
        formatStockInfo(true, instockList, instockIdIn, instockMap, managerIdIn, managerIdAttr, typeAttr, timeAttr, refIdAttr);
        //入库单关联的入库产品--内部处理好产品编号、产品分类、规格等信息
        List<InstockProductEntity> instockProductList = productHelp.getInstockProduct(instockIdIn, chartResultPojo.getCorpid());
        //置入库存pojo
        stockInfoPojo.setInstockMap(instockMap);
        stockInfoPojo.setInstockProductList(instockProductList);
        return stockInfoPojo;
    }

    /**
     * 得到出库产品相关信息pojo
     * @param chartResultPojo 参数pojo
     * @param managerIdIn 负责人userId数组
     * @param stockInfoPojo 出入库存pojo
     * @return java.util.List<com.xbongbong.saas.domain.entity.InstockProductEntity>
     * @throws XbbException
     * @author zcp
     * @date 2019/4/8 22:42
     * @since v1.0
     * @version v1.0
     */
    private StockInfoPojo getOutStockInfoPojo(ChartResultPojo chartResultPojo, Set<String> managerIdIn, StockInfoPojo stockInfoPojo) throws XbbException {
        OutstockEnum enumManagerId = OutstockEnum.MANAGER_ID;
        OutstockEnum enumType = OutstockEnum.TYPE;
        OutstockEnum enumTime = OutstockEnum.TIME;
        OutstockEnum enumRefId = OutstockEnum.REF_ID_LINKED_TEXT;
        List<String> fieldList = Arrays.asList(FieldTypeEnum.DATAID.getAlias(), FieldTypeEnum.OWNERID.getAlias(), FieldTypeEnum.SERIALNO.getAlias(), OutstockEnum.getAttrConnectData(enumManagerId), OutstockEnum.getAttrConnectData(enumType), OutstockEnum.getAttrConnectData(enumTime), OutstockEnum.getAttrConnectData(enumRefId));
        List<PaasFormDataEntityExt> outstockList = formHelp.getOutstockList(chartResultPojo, fieldList);
        //出库单关联的出库产品
        Set<Long> outstockIdIn = new HashSet<>();
        Map<Long, StockInfoVO> outstockMap = new HashMap<>(outstockList.size());
        String managerIdAttr = enumManagerId.getAttr();
        String typeAttr = enumType.getAttr();
        String timeAttr = enumTime.getAttr();
        String refIdAttr = enumRefId.getAttr();
        formatStockInfo(false, outstockList, outstockIdIn, outstockMap, managerIdIn, managerIdAttr, typeAttr, timeAttr, refIdAttr);
        //出库单关联的入库产品--内部处理好产品编号、产品分类、规格等信息
        List<OutstockProductEntity> outstockProductList = productHelp.getOutstockProduct(outstockIdIn, chartResultPojo.getCorpid());
        //置入库存pojo
        stockInfoPojo.setOutstockMap(outstockMap);
        stockInfoPojo.setOutstockProductList(outstockProductList);
        return stockInfoPojo;
    }

    /**
     * 格式化出入库信息，并把相应id置入集合为后续查询做准备
     * @param instockFlag 出入库flag true入库、false出库
     * @param stockList 出入库list
     * @param stockIdIn 出入库id集合
     * @param stockMap 出入库map：出入库id---出入库StockInfoVO
     * @param managerIdIn 出入库的负责人id集合
     * @param managerIdAttr 负责人英文字段
     * @param typeAttr 类型英文字段
     * @param timeAttr 出入库时间英文字段
     * @param refIdAttr 出入库关联单据的编号英文字段
     * @author zcp
     * @date 2019/4/9 14:08
     * @since v1.0
     * @version v1.0
     */
    private void formatStockInfo(boolean instockFlag, List<PaasFormDataEntityExt> stockList, Set<Long> stockIdIn, Map<Long, StockInfoVO> stockMap, Set<String> managerIdIn, String managerIdAttr, String typeAttr, String timeAttr, String refIdAttr) {
        for (PaasFormDataEntityExt entityExt : stockList) {
            Long dataId = entityExt.getDataId();
            stockIdIn.add(dataId);
            JSONObject data = JsonHelperUtil.getJSONObject(entityExt.getData());
            String managerId = entityExt.getOwnerId();
            managerIdIn.add(managerId);
            StockInfoVO stockInfoVO = new StockInfoVO();
            stockInfoVO.setManagerId(managerId);
            stockInfoVO.setSerialNo(entityExt.getSerialNo());
            if (instockFlag ) {
                //入库则按照入库InstockTypeEnum格式化入库类型
                stockInfoVO.setTypeName(InstockTypeEnum.getTypeNameByCode(data.getInteger(typeAttr)));
            }else {
                //出库则按照出库OutstockTypeEnum格式化出库类型
                stockInfoVO.setTypeName(OutstockTypeEnum.getTypeNameByCode(data.getInteger(typeAttr)));
            }
            stockInfoVO.setTime(DateUtil.getString(data.getInteger(timeAttr), DateUtil.SDFDate));
            stockInfoVO.setRefName(data.getString(refIdAttr));
            stockMap.put(dataId, stockInfoVO);
        }
    }
}
